﻿using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using AspnetUtil.Web.Config;
using AspnetUtil.Web.Filter.Auth;
using AspnetUtil.Web.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options;

namespace AspnetUtil.Web.Filter
{
    /// <summary>
    /// 登录过滤器
    /// </summary>
    public class AuthFilter : IAsyncActionFilter
    {
        private const string AuthHeader = "X-Token";
        private readonly IOptions<AuthSetting> _optionsAuth;

        public AuthFilter(IOptions<AuthSetting> optionsAuth)
        {
            _optionsAuth = optionsAuth;
        }


        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            // 请求信息
            var request = context.HttpContext.Request;

            if (!ExecFilter(request))
            {
                await next();
                return;
            }

            var token = "";
            token = request.Cookies[AuthHeader];
            if (token is null or "")
            {
                // 先从 cookie 获取, 再从 header 获取
                token = request.Headers[AuthHeader];
            }

            if (token is null or "")
            {
                await Abort(context);
                return;
            }

            // 解析 jwt token
            var claim = JwtAuthentication.Decode<long>(token);
            UserInfo userInfo = null;
            try
            {
                // 从缓存中获取用户信息
                userInfo = UserCache.GetUser(claim.Uid);
            }
            catch (Exception e)
            {
                // ignored
            }

            if (userInfo == null)
            {
                await Abort(context);
                return;
            }

            // 设置线程变量
            UserAttr.SetUser(userInfo);
            await next();
        }

        /// <summary>
        /// 判断是否忽略此链接
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private bool ExecFilter(HttpRequest request)
        {
            var exec = false;
            var path = request.Path.ToString();
            var value = _optionsAuth.Value;
            foreach (var s in value.Include)
            {
                exec = path.StartsWith(s);
                if (exec)
                {
                    break;
                }
            }

            var ignored = false;
            // 循环忽略的 url
            foreach (var s in value.Ignore)
            {
                ignored = path.Contains(s);
                if (ignored)
                {
                    break;
                }
            }


            return !ignored && exec;
        }

        /// <summary>
        ///  停止执行
        /// </summary>
        /// <param name="context"></param>
        private static async Task Abort(ActionContext context)
        {
            ApiResult<object> result = new()
            {
                Code = (int) HttpStatusCode.Unauthorized,
                Message = "尚未登录."
            };
            // 没有 token 信息 , 禁止向下执行
            await context.HttpContext.Response.WriteAsJsonAsync(result);
        }
    }
}